//=============================================================================
// Weapon stat generator	25-October-2012	Benjamin
//
// KNOWN ISSUES
//
//		Cannot detect where different fire modes share the same
//		ammo (boomstick)
//
//		Cannot detect penetration for all weapons, must check manually.
//
// ===== INFO
//
// HEAD SHOTS
//
// Every weapon's head shot multiplier is stored in its associated damagetype
// class, except (some of) those weapons whose projectiles implement
// ProcessTouch themselves: CrossbowArrow, M99Bullet CrossbuzzsawBlade. These
// projectiles have their own HeadShotDamageMult variable.
//
// NOTES
//
// (1) Certain classes don't use AmmoPerFire: MP7MAltFire, M7A3MAltFire
// (2) Hardcoded penetration values: Deagle, MK23, 44Magnum, Crossbow, M99,
// and Buzzsaw bow. Look in script files manually for these stats.
// (3) Weapons only have a single ReloadRate stat (none for alt-fire)
// (4) Weapons that auto-reload with a specific time: 
//
//     Hunting shotgun - ReloadCountDown stored in BoomStick.uc
//     M79 - FireRate (fire + reload are same animation)
//     Crossbow - FireRate (fire + reload are same animation)
//     LAW - FireRate (fire + reload are same animation)
//     M99 - FireRate (fire + reload are same animation)
//     Buzzsaw Bow - FireRate (fire + reload are same animation)
//=============================================================================
class WeaponConfig extends Mutator;

// Weapons
var array< class<KFWeaponPickup> > AdditionalWeapons;
var class<KFWeaponPickup> Pickup;
var class<KFWeapon> Weapon;
var class<WeaponFire> Fire[2];
var class<DamageType> DamageType;
//var class<InstantFire> InstantFire;
var class<BaseProjectileFire> BaseProjectileFire;
var class<Projectile> Projectile;
var class<KFMonster> KFM;

// Specimens
var int SpecimenCount;
var array<float> GameDifficulty;
var array<float> BountyMultiplier;
var array<float> HealthMultiplier;
var array<float> HeadHealthMultiplier;
var array<float> SpeedMultiplier;
var array<float> DamageMultiplier;

struct WeaponInfo
{
	var string WeaponClass;
	var array<int> Damage[2];
	var array<float> DamageMult[2];
	var array<float> HeadMult[2];
	var int Cost;
	var float CostMult;
	var int AmmoCost; // in pickup
	var array<float> AmmoCostMult[2];
	var array<int> Capacity[2];
	var array<float> CapacityMult[2];
	var int MagSize; // only 1
	var array<float> MagSizeMult;
	var int Weight;
	var float FireRate[2];
	var class<DamageType> DamageType[2];
};
var config array<WeaponInfo> WeaponCFG[200];
var int l,l2;
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
simulated function PreBeginPlay()
{
	local WeaponInfo WI;
	local int i,x;
	for (i=0;i<200;i++)
	{
		WI = WeaponCFG[i];
		if (Len(WI.WeaponClass)==0) continue;
		Weapon = class<KFWeapon>(DynamicLoadObject(WI.WeaponClass, Class'Class'));
		if (Weapon==none) continue;
		Pickup = class<KFWeaponPickup>(Weapon.default.PickupClass);
		if (Pickup==none) continue;
		for (x = 0; x < 2; x++)
		{
			if (Weapon.default.FireModeClass[x] != none && IsTrueFire(Weapon.default.FireModeClass[x]))
				Fire[x] = Weapon.default.FireModeClass[x];
			else
			{
				Fire[x] = none;
				continue;
			}
			if (class<BaseProjectileFire>(Fire[x])!=none)
				WeaponCFG[i].DamageType[x] = class<BaseProjectileFire>(Fire[x]).default.ProjectileClass.default.MyDamageType;
			else if (class<InstantFire>(Fire[x]) != none)
				WeaponCFG[i].DamageType[x] = class<InstantFire>(Fire[x]).default.DamageType;
		}
		default.WeaponCFG[i] = WeaponCFG[i];
	}
	WI.WeaponClass = "M41AAssaultRifle";
	WI.Damage[0] = 80;
	WI.DamageMult[0] = 1.0;
	SetWeaponStats();
}
//--------------------------------------------------------------------------------------------------
static function float GetDamageMult(class<DamageType> dtype)
{
	default.l = 0;
	for (default.l=0; default.l<200; default.l++)
	{
		for (default.l2=0; default.l2<2; default.l2++)
		{
			if (default.WeaponCFG[default.l].DamageType[default.l2] == dtype)
				return default.WeaponCFG[default.l].DamageMult[default.l2];
		}
	}
}
//--------------------------------------------------------------------------------------------------
//function GenerateWeaponStats()
function SetWeaponStats()
{
	local string	Name;
	local string	Perk;
	local int		Cost;
	local int		AmmoCost;
	local int		Weight;
	local int		Capacity[2];
	local int		MagazineSize[2];
	local float		FireRate[2];
	local float		ReloadSpeed[2];
	local float		Spread[2];
	local int		Damage[2];
	local float		DamageRadius[2];
	local float		HeadMultiplier[2];
	local int		Pellets[2];
	local int		MaxPens[2];
	local float		PenReduction[2];
	local float		Range;
	local int i, x;
	local WeaponInfo WI;
	
	for (i = 0; i < 200; i++)
	{
		WI = WeaponCFG[i];
		if (Len(WI.WeaponClass)==0) continue;
		Weapon = class<KFWeapon>(DynamicLoadObject(WI.WeaponClass, Class'Class'));
		if (Weapon==none) continue;
		Pickup = class<KFWeaponPickup>(Weapon.default.PickupClass);
		if (Pickup==none) continue;

		for (x = 0; x < 2; x++)
		{
			if (Weapon.default.FireModeClass[x] != none && IsTrueFire(Weapon.default.FireModeClass[x]))
				Fire[x] = Weapon.default.FireModeClass[x];
			else
				Fire[x] = none;
		}
		SetDamage(WI.Damage);
		SetHeadMultiplier(WI.HeadMult);
		SetCost(WI.Cost);
		SetAmmoCost(WI.AmmoCost);
		SetCapacity(WI.Capacity);
		SetMagazineSize(WI.MagSize);
		SetWeight(WI.Weight);
		SetFireRate(WI.FireRate);
		//SetDamageMult(WI.DamageMult);
		/*
		//GetName(Name);
		//GetPerk(Perk);
		//GetCost(Cost);
		//GetAmmoCost(AmmoCost);
		//GetWeight(Weight);
		//GetCapacity(Capacity);
		//GetMagazineSize(MagazineSize);
		//GetFireRate(FireRate);
		GetReloadSpeed(ReloadSpeed);
		GetSpread(Spread);
		//GetDamage(Damage);
		GetDamageRadius(DamageRadius);
		//GetHeadMultiplier(HeadMultiplier);
		GetPellets(Pellets);
		GetMaxPens(MaxPens);
		GetPenReduction(PenReduction);
		GetRange(Range);
		
		OutputStat("Name", 			Name);
		OutputStat("Perk",			Perk);	
		OutputStatNum("Cost", 		Cost);
		OutputStatNum("Weight",	 	Weight);
		OutputStatNum("Ammo cost",	AmmoCost);
		OutputStatNum("Capacity", 	Capacity[0], Capacity[1]);
		OutputStatNum("Magazine", 	MagazineSize[0], MagazineSize[1]);
		OutputStatNum("Damage", 	Damage[0], Damage[1]);
		OutputStatNum("Radius", 	DamageRadius[0], DamageRadius[0]);
		OutputStatNum("Head", 		HeadMultiplier[0], HeadMultiplier[1] );
		OutputStatNum("Pellets", 	Pellets[0], Pellets[1]);
		OutputStatNum("Spread", 	Spread[0], Spread[1]);
		OutputStatNum("Max pens",	MaxPens[0], MaxPens[1]);
		OutputStatNum("Pen reduc",	PenReduction[0], PenReduction[1]);
		OutputStatNum("Fire rate", 	FireRate[0], FireRate[1]);
		OutputStatNum("Reload sp",	ReloadSpeed[0], ReloadSpeed[1]);
		Log("");
		*/
	}
}
//--------------------------------------------------------------------------------------------------
function GenerateSpecimenStats()
{
	local string	Name;
	local int		Bounty[5];
	local int		Health[5];
	local float		HeadHealth[5];
	local float		Speed[5];
	local int		Damage[5];
	local float		Range;

	local KFGameType KF;
	local int i;
	
	KF = KFGameType(Level.Game);
	
	Log("===========================================================");
	Log("SPECIMEN STATS ============================================");
	Log("===========================================================");
	
	SpecimenCount = KF.StandardMonsterClasses.Length;
	for (i = 0; i < SpecimenCount; i++)
	{
		// Log("Specimen #" $ i $ ":" @ class'KFGameType'.default.StandardMonsterClasses[i].MClassName);
		
		KFM = class<KFMonster>(DynamicLoadObject(class'KFGameType'.default.
			StandardMonsterClasses[i].MClassName, class'class'));
		
		GetSpecimenName(Name);
		GetSpecimenBounty(Bounty);
		GetSpecimenHealth(Health);
		GetSpecimenHeadHealth(HeadHealth);
		GetSpecimenSpeed(Speed);
		GetSpecimenDamage(Damage);
		GetSpecimenRange(Range);
		
		Log("Name:       " $ Name);
		Log("Bounty:     " $ Bounty[0] @ Bounty[1] @ Bounty[2] @ Bounty[3] @ Bounty[4]);
		Log("Health:     " $ Health[0] @ Health[1] @ Health[2] @ Health[3] @ Health[4]);
		Log("HeadHealth: " $ HeadHealth[0] @ HeadHealth[1] @ HeadHealth[2] @ HeadHealth[3] @ HeadHealth[4]);
		Log("Speed:      " $ Speed[0] @ Speed[1] @ Speed[2] @ Speed[3] @ Speed[4]);
		Log("Damage:     " $ Damage[0] @ Damage[1] @ Damage[2] @ Damage[3] @ Damage[4]);
		Log("Range:      " $ Range);
		Log("");
	}

	Log("");
}
//--------------------------------------------------------------------------------------------------
/*function PostBeginPlay()
{
	GenerateWeaponStats();
	GenerateSpecimenStats();
}*/

///////////////////////////////////////////////////////////////////////////////
// SPECIMEN STAT CALCULATION
///////////////////////////////////////////////////////////////////////////////

function GetSpecimenName(out string Name)
{
	Name = KFM.default.MenuName;
}

function GetSpecimenBounty(out int KillScore[5])
{
	local int i;
	
	for (i = 0; i < 5; i++)
		KillScore[i] = Max(1, int(KFM.default.ScoringValue * BountyMultiplier[i]));
}

function GetSpecimenHealth(out int Health[5])
{
	local int i;

	for (i = 0; i < 5; i++)
		Health[i] = Ceil(KFM.default.Health * HealthMultiplier[i]);
}

function GetSpecimenHeadHealth(out float HeadHealth[5])
{
	local int i;

	for (i = 0; i < 5; i++)
		HeadHealth[i] = Ceil(KFM.default.HeadHealth * HeadHealthMultiplier[i]);
}

function GetSpecimenSpeed(out float Speed[5])
{
	local int i;

	for (i = 0; i < 5; i++)
		Speed[i] = KFM.default.GroundSpeed * SpeedMultiplier[i];
}

function GetSpecimenDamage(out int Damage[5])
{
	local int i;

	for (i = 0; i < 5; i++)
		Damage[i] = KFM.default.MeleeDamage * DamageMultiplier[i];
}

function GetSpecimenRange(out float Range)
{
	Range = KFM.default.MeleeRange;
}

///////////////////////////////////////////////////////////////////////////////
// WEAPON STAT CALCULATION
///////////////////////////////////////////////////////////////////////////////

function GetName(out string Name)
{
	Name = Pickup.default.ItemName;
}

function GetPerk(out string Perk)
{
	Perk = KFGameType(Level.Game).default.
		LoadedSkills[Pickup.default.CorrespondingPerkIndex].default.VeterancyName;
}
//--------------------------------------------------------------------------------------------------
function SetCost(int Cost)
{
	Pickup.default.Cost = Cost;
}
//--------------------------------------------------------------------------------------------------
function GetCost(out int Cost)
{
	Cost = Pickup.default.Cost;
}
//--------------------------------------------------------------------------------------------------
function SetAmmoCost(int AmmoCost)
{
	Pickup.default.AmmoCost = AmmoCost;
}
//--------------------------------------------------------------------------------------------------
function GetAmmoCost(out int AmmoCost)
{
	AmmoCost = Pickup.default.AmmoCost;
}
//--------------------------------------------------------------------------------------------------
function SetWeight(int Weight)
{
	Pickup.default.Weight = Weight;
}
//--------------------------------------------------------------------------------------------------
function GetWeight(out int Weight)
{
	Weight = Pickup.default.Weight;
}
//--------------------------------------------------------------------------------------------------
function SetCapacity(int Capacity[2], optional int Index)
{
	if (Index == 0) SetCapacity(Capacity, 1);
	if (Capacity[Index] == 0)
		return;
	if (Fire[Index] != none && !IsMeleeFire(Fire[Index]) && Fire[Index].default.AmmoClass != none)
		Fire[Index].default.AmmoClass.default.MaxAmmo = Capacity[Index];
}
//--------------------------------------------------------------------------------------------------
function GetCapacity(out int Capacity[2], optional int Index)
{
	Capacity[Index] = 0;
	if (Index == 0) GetCapacity(Capacity, 1);

	if (Fire[Index] != none && !IsMeleeFire(Fire[Index]) && Fire[Index].default.AmmoClass != none)
		Capacity[Index] = Fire[Index].default.AmmoClass.default.MaxAmmo;	
}
//--------------------------------------------------------------------------------------------------
function SetMagazineSize(int MagazineSize)
{
	 Weapon.default.MagCapacity = MagazineSize;
	//MagazineSize[1] = 0; // Can't be obtained normally
}
//--------------------------------------------------------------------------------------------------
function GetMagazineSize(out int MagazineSize[2])
{
	MagazineSize[0] = Weapon.default.MagCapacity;
	MagazineSize[1] = 0; // Can't be obtained normally
}
//--------------------------------------------------------------------------------------------------
function SetFireRate(float FireRate[2], optional int Index)
{
	if (Index == 0) SetFirerate(FireRate, 1);
	if (FireRate[Index] == 0) return;
	if (!IsAutoReloadingWeapon(Weapon)) // (4) Weapons that fire-reload in one animation
	{
		if (Fire[Index] != none)
			Fire[Index].default.FireRate = FireRate[Index];
	}
}
//--------------------------------------------------------------------------------------------------
function GetFireRate(out float FireRate[2], optional int Index)
{
	FireRate[Index] = 0;
	if (Index == 0) GetFirerate(FireRate, 1);
	
	if (IsAutoReloadingWeapon(Weapon)) // (4) Weapons that fire-reload in one animation
		FireRate[Index] = 0;
	else
	{
		if (Fire[Index] != none)
			FireRate[Index] = Fire[Index].default.FireRate;
	}
}
//--------------------------------------------------------------------------------------------------
function GetReloadSpeed(out float ReloadSpeed[2], optional int Index)
{
	ReloadSpeed[Index] = 0;
	if (Index == 0) GetReloadSpeed(ReloadSpeed, 1);
	
	if (IsAutoReloadingWeapon(Weapon)) // (4) Weapons that fire-reload in one animation
		if (Fire[Index] != none)
			ReloadSpeed[Index] = Fire[Index].default.FireRate;
	else
	{
		if (Fire[Index] != none)
			ReloadSpeed[Index] = Weapon.default.ReloadRate; // (3)
	}
}

function GetSpread(out float Spread[2], optional int Index)
{
	Spread[Index] = 0;
	if (Index == 0) GetSpread(Spread, 1);
	
	if (Fire[Index] != none)
		Spread[Index] = Fire[Index].default.Spread;
}
//--------------------------------------------------------------------------------------------------
function SetDamage(int Damage[2], optional int Index)
{
	local float diff;
	if (Index == 0) SetDamage(Damage, 1);	
	
	if (Damage[Index] == 0)
		return;
	
	if (Fire[Index] != none)
	{
		if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
		{
			diff = class<InstantFire>(Fire[Index]).default.DamageMin / class<InstantFire>(Fire[Index]).default.DamageMax;
			class<InstantFire>(Fire[Index]).default.DamageMax = Damage[Index];
			class<InstantFire>(Fire[Index]).default.DamageMin = diff * Damage[Index];
		}
		else if(class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
		{
			if (class<MP7MMedicGun>(Weapon) != none)
				class<MP7MMedicGun>(Weapon).default.HealBoostAmount = Damage[Index];
			else if (class<M7A3MMedicGun>(Weapon) != none)
				class<M7A3MMedicGun>(Weapon).default.HealBoostAmount = Damage[Index];
			else
				class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.Damage = Damage[Index];
		}
		else if (class<KFMeleeFire>(Fire[Index]) != none) // MELEE
		{
			//diff = class<KFMeleeFire>(Fire[Index]).default.MaxAdditionalDamage / class<KFMeleeFire>(Fire[Index]).default.MeleeDamage;
			class<KFMeleeFire>(Fire[Index]).default.MeleeDamage = Damage[Index];
			//class<KFMeleeFire>(Fire[Index]).default.MaxAdditionalDamage = Damage[Index] * diff;
		}
	}
}
//--------------------------------------------------------------------------------------------------
function GetDamage(out int Damage[2], optional int Index)
{
	Damage[Index] = 0;
	if (Index == 0) GetDamage(Damage, 1);	

	if (Fire[Index] != none)
	{
		if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
			Damage[Index] = class<InstantFire>(Fire[Index]).default.DamageMax;
		else if(class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
		{
			if (class<MP7MMedicGun>(Weapon) != none)
				Damage[Index] = class<MP7MMedicGun>(Weapon).default.HealBoostAmount;
			else if (class<M7A3MMedicGun>(Weapon) != none)
				Damage[Index] = class<M7A3MMedicGun>(Weapon).default.HealBoostAmount;
			else
				Damage[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.Damage;
		}
		else if (class<KFMeleeFire>(Fire[Index]) != none) // MELEE
		{
			Damage[Index] = class<KFMeleeFire>(Fire[Index]).default.MeleeDamage;
			//+class<KFMeleeFire>(Fire[Index]).default.MaxAdditionalDamage;
		}
	}
}
//--------------------------------------------------------------------------------------------------
function GetDamageRadius(out float DamageRadius[2], optional int Index)
{
	local class<DamageType> DT;
	
	DamageRadius[Index] = 0;
	if (Index == 0) GetDamageRadius(DamageRadius, 1);
	
	if (Fire[Index] != none && class<BaseProjectileFire>(Fire[Index]) != none)
	{
		DT = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.MyDamageType;
		if (class<KFWeaponDamageType>(DT) != none)
		{
			if (class<KFWeaponDamageType>(DT).default.bIsExplosive)
				DamageRadius[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.DamageRadius;
		}
	}
}
//--------------------------------------------------------------------------------------------------
function SetHeadMultiplier(float HeadMultiplier[2], optional int Index)
{
	local class<Projectile> P;

	if (Index == 0) SetHeadMultiplier(HeadMultiplier, 1);

	if (HeadMultiplier[Index] == 0)
		return;
	
	if (Fire[Index] != none)
	{
		if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
		{
			if (class<KFWeaponDamageType>(class<InstantFire>(Fire[Index]).default.DamageType) != none)
				class<KFWeaponDamageType>(
					class<InstantFire>(Fire[Index]).default.DamageType).default.HeadShotDamageMult = HeadMultiplier[Index];
		}
		else if (class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
		{
			P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;

			if (P == class'CrossbuzzsawBlade') // Buzzsaw bow
				class<CrossbuzzsawBlade>(P).default.HeadShotDamageMult = HeadMultiplier[Index];
			else if (P == class'CrossbowArrow') // CROSSBOW
				class<CrossbowArrow>(P).default.HeadShotDamageMult = HeadMultiplier[Index];
			else if (P == class'M99Bullet') // M99
				class<M99Bullet>(P).default.HeadShotDamageMult = HeadMultiplier[Index];
			else if ( P.default.MyDamageType != none &&
				class<KFWeaponDamageType>(P.default.MyDamageType) != none ) // ANY OTHER PROJECTILES USE DAMAGETYPE
					class<KFWeaponDamageType>(P.default.MyDamageType).default.HeadShotDamageMult = HeadMultiplier[Index];
		}
		else if (class<KFMeleeFire>(Fire[Index]) != none) // MELEE
		{
			if (class<DamTypeMelee>(class<KFMeleeFire>(Fire[Index]).default.hitDamageClass) != none)
				class<DamTypeMelee>(class<KFMeleeFire>(Fire[Index]).default.hitDamageClass).default.HeadShotDamageMult = HeadMultiplier[Index];
		}
	}
}
//--------------------------------------------------------------------------------------------------
function GetHeadMultiplier(out float HeadMultiplier[2], optional int Index)
{
	local class<Projectile> P;

	HeadMultiplier[Index] = 1.0;
	if (Index == 0) GetHeadMultiplier(HeadMultiplier, 1);
	
	if (Fire[Index] != none)
	{
		if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
		{
			if (class<KFWeaponDamageType>(class<InstantFire>(Fire[Index]).default.DamageType) != none)
				HeadMultiplier[Index] = class<KFWeaponDamageType>(
					class<InstantFire>(Fire[Index]).default.DamageType).default.HeadShotDamageMult;
		}
		else if (class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
		{
			P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;

			if (P == class'CrossbuzzsawBlade') // Buzzsaw bow
				HeadMultiplier[Index] = class<CrossbuzzsawBlade>(P).default.HeadShotDamageMult;
			else if (P == class'CrossbowArrow') // CROSSBOW
				HeadMultiplier[Index] = class<CrossbowArrow>(P).default.HeadShotDamageMult;
			else if (P == class'M99Bullet') // M99
				HeadMultiplier[Index] = class<M99Bullet>(P).default.HeadShotDamageMult;
			else if ( P.default.MyDamageType != none &&
				class<KFWeaponDamageType>(P.default.MyDamageType) != none ) // ANY OTHER PROJECTILES USE DAMAGETYPE
					HeadMultiplier[Index] = class<KFWeaponDamageType>(P.default.MyDamageType).default.HeadShotDamageMult;
		}
		else if (class<KFMeleeFire>(Fire[Index]) != none) // MELEE
		{
			if (class<DamTypeMelee>(class<KFMeleeFire>(Fire[Index]).default.hitDamageClass) != none)
				HeadMultiplier[Index] = class<DamTypeMelee>(class<KFMeleeFire>(Fire[Index]).default.hitDamageClass).default.HeadShotDamageMult;
		}
	}
}
//--------------------------------------------------------------------------------------------------
function GetPellets(out int Pellets[2], optional int Index)
{
	Pellets[Index] = 0;
	if (Index == 0) GetPellets(Pellets, 1);

	if (Fire[Index] != none && class<KFShotgunFire>(Fire[Index]) != none)
	{
		if (IgnoresLoad(Fire[Index])) // (1) see note
			Pellets[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjPerFire;
		else
		Pellets[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjPerFire *
			class<BaseProjectileFire>(Fire[Index]).default.AmmoPerFire;
	}
}

function GetMaxPens(out int MaxPens[2], optional int Index)
{
	local class<Projectile> P;

	MaxPens[Index] = 0;
	if (Index == 0) GetMaxPens(MaxPens, 1);
	
	if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
	{
		// (2) Deagle, MK23, 44Magnum
	}
	else if (class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
	{
		P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
		
		if (class<ShotgunBullet>(P) != none)
			MaxPens[Index] = class<ShotgunBullet>(P).default.MaxPenetrations;
	}
}

function GetPenReduction(out float PenReduction[2], optional int Index)
{
	local class<Projectile> P;

	PenReduction[Index] = 0;
	if (Index == 0) GetPenReduction(PenReduction, 1);
	
	if (class<BaseProjectileFire>(Fire[Index]) != none)
	{
		P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
		if (class<ShotgunBullet>(P) != none)
			PenReduction[Index] = class<ShotgunBullet>(P).default.PenDamageReduction;
	}
}

function GetRange(out float Range)
{
	if (class<KFMeleeFire>(Fire[0]) != none)
		Range = class<KFMeleeFire>(Fire[0]).default.WeaponRange;
	else
		Range = 0;
}

// Utilities

function bool IsTrueFire(class<WeaponFire> Fire)
{
	if (Fire.Name == 'NoFire'
		|| Fire.Name == 'ShotgunLightFire'
		|| Fire.Name == 'SingleALTFire'
		)
		return false;
	
	return true;
}

function bool IsMeleeFire(class<WeaponFire> Fire)
{
	if (Fire == none)
		return false;
	if (class<KFMeleeFire>(Fire) != none)
		return true;
	return false;
}

function bool IgnoresLoad(class<WeaponFire> Fire)
{
	if (class<MP7MAltFire>(Fire) != none
		|| class<M7A3MAltFire>(Fire) != none)
		
		return true;
	
	return false;
}

function bool IsAutoReloadingWeapon(class<Weapon> Weapon) // (4)
{
	if (Weapon == class'KFMod.Boomstick')
		return true;
	else if (Weapon == class'KFMod.M79GrenadeLauncher')
		return true;
	else if (Weapon == class'KFMod.Crossbow')
		return true;
	else if (Weapon == class'KFMod.LAW')
		return true;
	else if (Weapon == class'KFMod.M99SniperRifle')
		return true;
	else if (Weapon == class'KFMod.Crossbuzzsaw')
		return true;

	return false;
}

defaultproperties
{
	GroupName="KFStatOutputMut"
	FriendlyName"KFStatOutput"
	Description="..."
	GameDifficulty=(1.0, 2.0, 4.0, 5.0, 7.0)
	BountyMultiplier=(2.0, 1.0, 0.85, 0.65, 0.65)
	HealthMultiplier=(0.5, 1.0, 1.35, 1.55, 1.75)
	HeadHealthMultiplier=(0.5, 1.0, 1.35, 1.55, 1.75)
	SpeedMultiplier=(0.95, 1.0, 1.15, 1.22, 1.3)
	DamageMultiplier=(0.3, 1.0, 1.25, 1.50, 1.75)
}